﻿#include "dXml.h"
#include <QDir>
#include "XmlDataDoc.h"
#include <QtXml/QtXml>

QDomElement dXml::toDocElement(QDomDocument& doc, XmlDataUnit* node) {
	QString tagName = node->nodeName( );
	QDomElement thisElement = doc.createElement(tagName.isEmpty( )
		? "defalut"
		: tagName);
	QList<XmlDataUnit*>* xmlDataUnits = node->getChildrens( );
	int len = xmlDataUnits->length( );
	if( len ) {
		for( int i = 0;i < len;++i ) {
			QDomElement element = toDocElement(doc, xmlDataUnits->at(i));
			thisElement.appendChild(element);
		}
	} else {
		QDomText textNode = doc.createTextNode(node->getText( ));
		thisElement.appendChild(textNode);
	}
	QHash<QString, QString>* attrs = node->getAttrs( );
	// 设置属性
	QHash<QString, QString>::iterator iterator = attrs->begin( );
	QHash<QString, QString>::iterator end = attrs->end( );
	for( ;iterator != end;++iterator ) {
		thisElement.setAttribute(iterator.key( ), iterator.value( ));
	}
	/*QDomComment domComment = doc.createComment(node.getComment('\n'));
	thisElement.appendChild(domComment);*/

	return thisElement;
}

bool dXml::save(QList<XmlDataUnit*>& nodes, const QString& file, QDomDocument* qDomDocument, int tabSize, QDomNode::EncodingPolicy edcoding) {
	bool hasProcessingInstruction = false;
	if( qDomDocument != Q_NULLPTR ) {
		QDomNodeList list = qDomDocument->childNodes( );
		int length = list.length( );
		for( int i = 0;i < length;++i ) {
			QDomNode domNode = list.at(i);
			if( domNode.isProcessingInstruction( ) ) {
				hasProcessingInstruction = true;
				break;
			}
		}
	} else {
		qDomDocument = new QDomDocument( );
	}
	if( !hasProcessingInstruction ) {
		QDomProcessingInstruction processingInstruction = qDomDocument->createProcessingInstruction(dXml::getProcessingInstructionTarget( ), dXml::getProcessingInstructionData( ));
		qDomDocument->insertBefore(processingInstruction, qDomDocument->firstChild( ));
	}
	QList<XmlDataUnit*>::iterator iterator = nodes.begin( );
	QList<XmlDataUnit*>::iterator end = nodes.end( );
	for( ;iterator != end;++iterator )
		qDomDocument->appendChild(dXml::toDocElement(*qDomDocument, *iterator));
	QDir dir;
	QFileInfo info(file);
	dir.mkpath(info.absolutePath( ));
	QFile writefile(file);
	if( !writefile.open(QIODevice::WriteOnly | QIODevice::Unbuffered) )
		return false;
	QTextStream outStream(&writefile);
	qDomDocument->save(outStream, tabSize, edcoding);
	delete qDomDocument;
	writefile.close( );
	return true;
}

void dXml::domDocumentToDxmlUnitDoc(dXml::XmlDataUnit* saveToData, QString& outPITarget, QString& outPIData, QDomDocument doc) {
	QDomNodeList domNodeList = doc.childNodes( );
	int listSize = domNodeList.length( );
	for( int index = 0;index < listSize;++index ) {
		QDomNode domNode = domNodeList.at(index);
		dXml::XmlDataUnit* xmlDataUnit = Q_NULLPTR;
		if( domNode.isElement( ) ) {
			// 获取对象
			QDomElement element = domNode.toElement( );
			saveToData->setName(element.tagName( ));
			// 获取属性
			QDomNamedNodeMap attriMap = element.attributes( );
			int length = attriMap.length( );
			for( int attrIndex = 0;attrIndex < length;++attrIndex ) {
				QDomNode item = attriMap.item(attrIndex);
				if( item.isAttr( ) ) {
					QDomAttr attr = item.toAttr( );
					QString attrName = attr.name( );
					QString attrValte = attr.value( );
					saveToData->appendAttr(attrName, attrValte);
				}
			}
		}
		if( domNode.isProcessingInstruction( ) ) {
			QDomProcessingInstruction instruction = domNode.toProcessingInstruction( );
			outPITarget = instruction.target( );
			outPIData = instruction.data( );
		}
		if( domNode.isText( ) ) {
			QDomText text = domNode.toText( );
			saveToData->setText(text.data( ));
		}
		QList<dXml::XmlDataUnit*> dataUnits = docChildRootNodesToXmlDataUnity(domNode.childNodes( ), saveToData);
		QList<dXml::XmlDataUnit*>::iterator iterator = dataUnits.begin( );
		QList<dXml::XmlDataUnit*>::iterator end = dataUnits.end( );
		for( ;iterator != end;++iterator ) {
			saveToData->appendChildren(*iterator);
		}
	}
}

bool dXml::readStringToXml(XmlDataUnit* saveToData, QString& outPITarget, QString& outPIData, const QString& strStream) {
	QDomDocument doc;
	if( ! doc.setContent(strStream) ) {
		return false;
	}
	domDocumentToDxmlUnitDoc(saveToData, outPITarget, outPIData, doc);
	return true;
}

bool dXml::readXmlFile(XmlDataUnit* saveToData, QString& outPITarget, QString& outPIData, const QString& file) {
	QFile readFile(file);
	if( !readFile.open(QIODevice::ReadOnly | QIODevice::Text) )
		return false;
	QDomDocument doc;
	QByteArray bytes = readFile.readAll( );
	QTextCodec* codec = QTextCodec::codecForName("utf-8");
	auto&& fileToText = codec->toUnicode(bytes);
	readFile.close( );
	doc.setContent(fileToText);

	/*QDomNodeList domNodeList = doc.childNodes( );
	int listSize = domNodeList.length( );
	for( int index = 0;index < listSize;++index ) {
		QDomNode domNode = domNodeList.at(index);
		XmlDataUnit* xmlDataUnit = Q_NULLPTR;
		if( domNode.isElement( ) ) {
			// 获取对象
			QDomElement element = domNode.toElement( );
			saveToData->setName(element.tagName( ));
			// 获取属性
			QDomNamedNodeMap attriMap = element.attributes( );
			int length = attriMap.length( );
			for( int attrIndex = 0;attrIndex < length;++attrIndex ) {
				QDomNode item = attriMap.item(attrIndex);
				if( item.isAttr( ) ) {
					QDomAttr attr = item.toAttr( );
					QString attrName = attr.name( );
					QString attrValte = attr.value( );
					saveToData->appendAttr(attrName, attrValte);
				}
			}
		}
		if( domNode.isProcessingInstruction( ) ) {
			QDomProcessingInstruction instruction = domNode.toProcessingInstruction( );
			outPITarget = instruction.target( );
			outPIData = instruction.data( );
		}
		if( domNode.isText( ) ) {
			QDomText text = domNode.toText( );
			saveToData->setText(text.data( ));
		}
		QList<dXml::XmlDataUnit*> dataUnits = docChildRootNodesToXmlDataUnity(domNode.childNodes( ), saveToData);
		QList<dXml::XmlDataUnit*>::iterator iterator = dataUnits.begin( );
		QList<XmlDataUnit*>::iterator end = dataUnits.end( );
		for( ;iterator != end;++iterator ) {
			saveToData->appendChildren(*iterator);
		}
	}*/

	domDocumentToDxmlUnitDoc(saveToData, outPITarget, outPIData, doc);
	return true;
}

QList<dXml::XmlDataUnit*> dXml::docChildRootNodesToXmlDataUnity(const QDomNodeList& domNodes, XmlDataUnit* paren) {
	QList<XmlDataUnit*> result;
	if( !domNodes.isEmpty( ) ) {
		int size = domNodes.size( );
		for( int index = 0;index < size;++index ) {
			XmlDataUnit* xmlDataUnit = Q_NULLPTR;
			QDomNode domNode = domNodes.at(index);
			if( domNode.isElement( ) ) {
				// 获取对象
				QDomElement element = domNode.toElement( );
				xmlDataUnit = new XmlDataUnit(element.tagName( ));
				result.append(xmlDataUnit);
				// 获取属性
				QDomNamedNodeMap attriMap = element.attributes( );
				int length = attriMap.length( );
				for( int attrIndex = 0;attrIndex < length;++attrIndex ) {
					QDomNode item = attriMap.item(attrIndex);
					if( item.isAttr( ) ) {
						QDomAttr attr = item.toAttr( );
						QString attrName = attr.name( );
						QString attrValte = attr.value( );
						xmlDataUnit->appendAttr(attrName, attrValte);
					}
				}
			}
			if( domNode.isText( ) ) {
				QDomText text = domNode.toText( );
				paren->setText(text.data( ));
			}
			QList<dXml::XmlDataUnit*> dataUnits = docChildRootNodesToXmlDataUnity(domNode.childNodes( ), xmlDataUnit);
			QList<dXml::XmlDataUnit*>::iterator iterator = dataUnits.begin( );
			QList<XmlDataUnit*>::iterator end = dataUnits.end( );
			for( ;iterator != end;++iterator ) {
				xmlDataUnit->appendChildren(*iterator);
			}
		}
	}
	return result;
}

/*inline const char* dXml::getProcessingInstructionTarget( ) {
	static const char* instance = "xml";
	return instance;
}

inline const char* dXml::getProcessingInstructionData( ) {
	static const char* instance = "version=\"1.0\" encoding=\"UTF-8\"";
	return instance;
}*/

/*
 *
 *const char* getProcessingInstructionTarget( ); {
		
	}
 * 
 */
/*
 *
 * {
		
	}
 */
